
import javax.swing.*;              // 导入Swing GUI组件库（如JButton、JPanel）
import java.awt.*;                 // 导入AWT库（用于布局管理和颜色设置）
import java.awt.event.ActionEvent; // 导入事件处理类（处理按钮点击等操作）
import java.awt.event.ActionListener; // 导入事件监听器接口
import java.awt.event.KeyAdapter;  // 导入键盘事件适配器
import java.awt.event.KeyEvent;    // 导入键盘事件类
import java.time.LocalDate;        // 导入日期类（用于显示当前日期）
import java.time.LocalTime;        // 导入时间类（用于显示当前时间）
import javax.script.ScriptEngine;  // 导入脚本引擎接口（用于计算数学表达式）
import javax.script.ScriptEngineManager; // 导入脚本引擎管理器
import javax.script.ScriptException; // 导入脚本异常类

/**
 * 高级科学计算器类
 * 功能：实现基本四则运算、科学计算（三角函数、对数等）、日期时间显示
 * 优化：改进输入逻辑控制、美化界面、添加键盘支持
 * 拓展：新增科学计算功能、按功能分类按钮颜色
 */
public class Calculator extends JFrame implements ActionListener {
    private JPanel north, center;    // 顶部面板（放文本框）和中间面板（放按钮）
    private JTextField field;       // 显示计算结果和输入内容的文本框
    private JButton[] btns;         // 按钮数组（存储所有按钮）

    // 构造方法：初始化计算器窗口
    public Calculator() {
        setTitle("高级科学计算器");       // 优化: 更新窗口标题，提升用户识别度
        setSize(800, 700);           // 优化: 增大窗口尺寸，容纳更多按钮
        setDefaultCloseOperation(EXIT_ON_CLOSE); // 设置关闭窗口时退出程序
        setLocationRelativeTo(null);  // 窗口居中显示，提升用户体验
        initComponent();              // 调用初始化界面组件的方法
        setVisible(true);             // 显示窗口
        
        // 拓展: 添加键盘事件监听，支持键盘输入
        // 算法逻辑：通过KeyAdapter监听键盘事件，将按键映射到对应按钮功能
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                handleKeyPress(e.getKeyChar()); // 将键盘输入映射到对应按钮功能
            }
        });
        setFocusable(true); // 修复: 修正语法错误，正确设置窗口可获取焦点
        requestFocusInWindow(); // 确保窗口初始化后立即获取焦点，响应键盘事件
    }

    // 初始化界面组件的方法
    private void initComponent() {
        getContentPane().setBackground(new Color(240, 240, 240)); // 优化: 设置浅灰色背景，提升可读性
        
        north = new JPanel();         // 创建顶部面板（用于放置文本框）
        center = new JPanel();        // 创建中间面板（用于放置按钮网格）
        
        // 优化: 美化文本框样式，提升用户体验
        field = new JTextField();
        field.setPreferredSize(new Dimension(800, 150)); // 设置文本框大小
        field.setEditable(false);     // 禁止手动输入，只能通过按钮操作，防止输入错误
        field.setFont(new Font("Microsoft YaHei", Font.BOLD, 35)); // 优化: 中文字体支持
        field.setHorizontalAlignment(JTextField.RIGHT); // 优化: 文本右对齐，符合计算器使用习惯
        field.setBackground(new Color(255, 255, 255)); // 优化: 白色背景
        field.setForeground(new Color(51, 51, 51));   // 优化: 深灰色文本，提高对比度
        field.setBorder(BorderFactory.createLineBorder(new Color(200, 200, 200), 2)); // 优化: 添加边框，增强视觉效果
        
        // 拓展: 新增科学计算按钮（sin, cos, tan, ln, log），扩展计算器功能
        // 算法逻辑：使用5x5网格布局，新增科学计算功能区
        String[] str = new String[] {
            "7", "8", "9", "+", "sin",
            "4", "5", "6", "-", "cos",
            "1", "2", "3", "×", "tan",
            "0", ".", "=", "÷", "ln",
            "C", "B", "T", "S", "W"
        };
        
        btns = new JButton[str.length];
        for (int i = 0; i < btns.length; i++) {
            btns[i] = new JButton(str[i]);
            
            // 优化: 根据按钮类型设置不同颜色（视觉区分），提升用户体验
            // 算法逻辑：通过按钮索引判断功能类型，设置不同颜色
            if (i >= 16) { // 功能按钮(C,B,T,S)
                btns[i].setBackground(new Color(230, 100, 100)); // 红色系，突出功能按钮
                btns[i].setForeground(Color.WHITE);
            } else if (i % 5 == 4) { // 科学计算按钮（拓展）
                btns[i].setBackground(new Color(180, 100, 230)); // 紫色系，区分科学计算功能
                btns[i].setForeground(Color.WHITE);
            } else if (i % 5 == 3) { // 运算符按钮(+, -, ×, ÷, =)
                btns[i].setBackground(new Color(100, 150, 230)); // 蓝色系，突出运算符
                btns[i].setForeground(Color.WHITE);
            } else { // 数字按钮
                btns[i].setBackground(new Color(250, 250, 250)); // 浅灰色，简洁明了
                btns[i].setForeground(new Color(51, 51, 51));
            }
            
            // 优化: 统一按钮样式，提升界面美观度
            btns[i].setBorder(BorderFactory.createLineBorder(new Color(200, 200, 200), 1));
            btns[i].setFocusPainted(false); // 移除焦点边框，使界面更简洁
            btns[i].setFont(new Font("Microsoft YaHei", Font.BOLD, 25)); // 中文字体
        }
        
        // 优化: 设置面板布局并添加间距，提升界面美观度
        north.setLayout(new BorderLayout());
        center.setLayout(new GridLayout(5, 5, 5, 5)); // 5×5网格布局，间距5px
        
        north.add(field, BorderLayout.CENTER); // 将文本框添加到顶部面板
        
        for (JButton btn : btns) {
            center.add(btn); // 将所有按钮添加到中间面板
        }
        
        // 将面板添加到窗口
        add(north, BorderLayout.NORTH);  // 将顶部面板添加到窗口北部
        add(center, BorderLayout.CENTER); // 将中间面板添加到窗口中央
        
        // 为所有按钮注册事件监听器
        for (JButton btn : btns) {
            btn.addActionListener(this); // 点击按钮时触发actionPerformed方法
        }
    }

    // 核心方法：处理按钮点击（含输入控制）
    private void setBtnText(String text) {
        String currentText = field.getText(); // 获取当前文本框内容
        
        // === 优化: 输入逻辑控制 ===
        // 算法逻辑：对特殊输入（运算符、小数点）进行前置校验，防止非法输入
        if (isOperator(text)) {
            if (currentText.isEmpty()) return; // 禁止空输入添加运算符，防止错误输入
            if (isOperator(currentText.charAt(currentText.length() - 1))) return; // 禁止连续运算符
        } 
        else if (text.equals(".")) {
            if (currentText.isEmpty()) {
                field.setText("0."); // 自动补零（优化），提升用户体验
                return;
            }
            // 修复: 正确处理负数（如-3.14），使用更精确的正则表达式分割字符串
            // 算法逻辑：使用正则表达式"(?<=[+\\-×÷])|(?=[+\\-×÷])"分割字符串，正确识别负数
            String[] parts = currentText.split("(?<=[+\\-×÷])|(?=[+\\-×÷])");
            String lastPart = parts[parts.length - 1];
            if (lastPart.contains(".")) return; // 禁止重复小数点
        }
        
        // === 拓展: 科学计算功能 ===
        // 算法逻辑：对科学计算按钮，先解析当前文本为数字，再调用对应数学函数计算
        if (isScientificFunction(text)) {
            try {
                double value = Double.parseDouble(currentText);
                double result = calculateScientificFunction(text, value);
                field.setText(String.valueOf(result));
            } catch (NumberFormatException e) {
                field.setText("错误: 请先输入数字");
            }
            return; // 计算后直接返回，不追加文本
        }
        
        // 处理其他按钮功能
        switch (text) {
            case "C":
                field.setText(""); // 清空文本框
                break;
            case "B":
                if (!currentText.isEmpty()) {
                    field.setText(currentText.substring(0, currentText.length() - 1)); // 删除最后一个字符
                }
                break;
            case "T":
                field.setText(LocalTime.now().toString()); // 显示当前时间
                break;
            case "S":
                field.setText(LocalDate.now().toString()); // 显示当前日期
                break;
            case "=":
                // === 表达式计算算法 ===
                // 算法逻辑：将界面表达式中的×÷替换为*/，使用JavaScript引擎计算结果
                try {
                    String expression = currentText.replace("×", "*").replace("÷", "/");
                    ScriptEngineManager manager = new ScriptEngineManager();
                    ScriptEngine engine = manager.getEngineByName("JavaScript");
                    double result = Double.parseDouble(engine.eval(expression).toString());
                    field.setText(String.valueOf(result));
                } catch (Exception e) {
                    field.setText("错误"); // 计算出错时显示"错误"
                }
                break;
            default:
                field.setText(currentText + text); // 数字或运算符：直接追加到文本框
                break;
        }
    }
    
    // 判断是否为运算符的辅助方法
    private boolean isOperator(String text) {
        return text.equals("+") || text.equals("-") || text.equals("×") || text.equals("÷");
    }
    
    private boolean isOperator(char c) {
        return c == '+' || c == '-' || c == '×' || c == '÷';
    }
    
    // 拓展: 判断是否为科学计算函数的辅助方法
    private boolean isScientificFunction(String text) {
        return text.equals("sin") || text.equals("cos") || text.equals("tan") || 
               text.equals("ln") || text.equals("log");
    }
    
    // 拓展: 计算科学函数结果的方法
    // 算法逻辑：根据函数类型，调用Java Math库对应函数，角度值需先转为弧度
    private double calculateScientificFunction(String func, double value) {
        switch (func) {
            case "sin": return Math.sin(Math.toRadians(value)); // 角度转弧度计算
            case "cos": return Math.cos(Math.toRadians(value));
            case "tan": return Math.tan(Math.toRadians(value));
            case "ln": return Math.log(value); // 自然对数
            case "log": return Math.log10(value); // 常用对数
            default: return value;
        }
    }
    
    // 拓展: 键盘事件处理方法
    // 算法逻辑：将键盘按键映射到对应按钮功能，实现键盘输入支持
    private void handleKeyPress(char keyChar) {
        String keyText = Character.toString(keyChar);
        
        // 数字键
        if (keyChar >= '0' && keyChar <= '9') {
            setBtnText(keyText);
        } 
        // 运算符键
        else if (keyChar == '+' || keyChar == '-' || keyChar == '*' || keyChar == '/') {
            setBtnText(keyText.replace('*', '×').replace('/', '÷')); // 转换为界面符号
        } 
        // 小数点
        else if (keyChar == '.') {
            setBtnText(".");
        } 
        // 回车键（等于号）
        else if (keyChar == '\n') {
            setBtnText("=");
        } 
        // 退格键
        else if (keyChar == '\b') {
            setBtnText("B");
        } 
        // 清空键（Esc键）
        else if (keyChar == 27) { // Esc键码为27
            setBtnText("C");
        }
    }

    // 实现ActionListener接口的方法，处理按钮点击事件
    @Override
    public void actionPerformed(ActionEvent a) {
        Object source = a.getSource();
        if (source instanceof JButton) {
            JButton btn = (JButton) source;
            String text = btn.getText();
            setBtnText(text); // 调用核心处理方法
        }
    }

    // 程序入口点：在事件调度线程中创建计算器实例
    public static void main(String[] args) {
        // 使用SwingUtilities.invokeLater确保GUI组件在事件调度线程中创建和操作
        // 避免线程安全问题
        SwingUtilities.invokeLater(Calculator::new);
    }
}